package com.cskaoyan.javase.oop3._2inner._3local._4life;

/**
 * 思考:
 *      在作用域外部,还能不能直接访问局部内部类? 不能
 *      但是,在作用域外部,还能不能访问局部内部类对象? 可以
 *      只需要方法将作用域内部的局部内部类对象作为方法的返回值,提供给外界就可以了.
 *      从这个角度上来说,局部内部类对象可能会一直被使用,一直存在.
 *
 * 如果局部内部类中,访问作用域内部的局部变量,那么就有可能出现生命周期的冲突:
 *      方法调用结束,局部变量销毁
 *      但局部内部类对象仍然存在,仍然要访问该局部变量
 *      那么这个局部变量去哪里找呢?
 *
 * 为了解决这个生命周期的冲突问题,JVM在创建"访问了作用域内部局部变量的局部内部类对象时"
 * 会将被访问的这个局部变量,作为局部内部类对象的成员变量
 * 这样,从代码上看,访问的是局部变量,但实际上访问的是自身成员变量
 *
 * 这就是Java解释生命周期冲突问题时,提出的解决方案.
 * 那么以上,和该局部变量是一个常量有什么关系呢?
 *  1.代码上看起来访问的是局部变量,但实际访问的是成员变量
 *  2.解决问题需要拿出方案,但解决问题的方案本身可能也是一个问题,或者会引入新的问题.
 * 在以上的前提下,假如允许"被局部内部类访问的局部变量"的修改,那么就有了新的问题: 同步问题
 *      实际上修改的是成员变量,但代码上看到的是修改局部变量,于是需要同步成员变量的修改到局部变量中
 * 但是,Java设计者没有采取这种同步的做法,干脆直接禁止修改,那么就不会出现同步问题了.
 *
 * 扩展:
 *      实际上在Java7以及以前的JDK版本中,局部内部类访问局部变量
 *      那么该局部变量必须用final修饰
 *      但是到了Java8以后,开发者将final隐藏在了底层,这是一种"语法糖"
 *      只要不修改这个局部变量,都是允许的
 *
 *      后面学习的 匿名内部类 和 Lambda表达式 本质依然是局部内部类，这一条注意事项仍然生效。
 *
 * @since 11:26
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        EnclosedClazz ec = new EnclosedClazz();
        IA ia = ec.test();
        ia.testInner();
    }
}

class EnclosedClazz {
    // class A{}
    // static class A{}
    public IA test() {
        // 在外围类的成员方法中,定义局部变量a
        int a = 666;
        class Inner implements IA {
            @Override
            public void testInner() {
                System.out.println(a);
            }
        }
        return new Inner();
    }

    public void test2() {
        class Inner {
        }
    }
}

interface IA {
    void testInner();
}